home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / Mac OS USB DDK_v1.0.1 / Examples / UniversalModule / UniversalHIDAPI.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-03  |  7.4 KB  |  267 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        UniversalHIDAPI.c
  3.  
  4.     Contains:    HID Emulation glue code between the ADB SHIM and the USB Mouse HID Module
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <Errors.h>
  16. #include <USB.h>
  17.  
  18. #include "UniversalHIDModule.h"            // this is the prototype for all HIDModules that follow the UHID spec
  19.  
  20.  
  21. #include "UniversalModule.h"            // this is the header for our specific driver
  22.  
  23. extern    usbUniversalPBStruct myUniversalPB;
  24.  
  25. // globals
  26. Boolean                     deviceIsClaimed = false;
  27. UHIDModuleConnectionID        currentConnectionID = 0;
  28.  
  29. RoutineDescriptor        interruptCallback =
  30. BUILD_ROUTINE_DESCRIPTOR(uppUserFnProcInfo, DeferredNotifyRegisteredHIDUser);
  31.  
  32. // entry points
  33. OSStatus UHIDInstallInterrupt(UHIDModuleConnectionID connectionID, UHIDInterruptProcPtr pInterruptProc, UInt32 refcon)
  34. {
  35.     // only allow our current clien to do this
  36.     if (connectionID != currentConnectionID)
  37.         return permErr;
  38.     
  39.     // clear our ring buffer
  40.     myUniversalPB.deferredHIDRing_Head = myUniversalPB.deferredHIDRing_Tail = 0;
  41.     
  42.     // log what we're gonna do
  43.     if (pInterruptProc)
  44.         USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine installed", myUniversalPB.interfaceRef);
  45.     else
  46.         USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine removed", myUniversalPB.interfaceRef);
  47.     
  48.     // actually change it
  49.     myUniversalPB.pClientInterruptRoutine = pInterruptProc;
  50.     myUniversalPB.clientRefCon = refcon;
  51.     return noErr;
  52. }
  53.  
  54. OSStatus UHIDControlDevice(UHIDModuleConnectionID connectionID, UInt32 theControlSelector, void * theControlData)
  55. {
  56. #pragma unused (theControlData)
  57.  
  58.     // only allow our current client to do this
  59.     if (connectionID != currentConnectionID)
  60.         return permErr;
  61.     
  62.     switch (theControlSelector)
  63.     {
  64.         case kUHIDRemoveInterruptHandle:
  65.             USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: Interrupt service routine removed", myUniversalPB.interfaceRef);
  66.             myUniversalPB.pClientInterruptRoutine = nil;
  67.             break;
  68.             
  69.         default:
  70.             return kUSBInternalErr;
  71.     }
  72.     
  73.     return noErr;
  74. }
  75.  
  76. OSStatus UHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  77. {
  78. UInt16 * pTheID;
  79. UInt32 * pTheSize;
  80.     
  81.     // we don't need a connection, because we want anyone to be ablt to do these
  82.     
  83.     switch (theInfoSelector)
  84.     {
  85.         case kUHIDGetVenderID:
  86.             pTheID = (UInt16*)theInfo;
  87.             *pTheID = (UInt16)(USBToHostWord(myUniversalPB.deviceDescriptor.vendor));
  88.             return noErr;
  89.             
  90.         case kUHIDGetProductID:
  91.             pTheID = (UInt16*)theInfo;
  92.             *pTheID = (UInt16)(USBToHostWord(myUniversalPB.deviceDescriptor.product));
  93.             return noErr;
  94.         
  95.         case kUHIDGetMaxPacketSize:
  96.             pTheSize = (UInt32*)theInfo;
  97.             *pTheSize = (UInt32)(myUniversalPB.maxPacketSize);
  98.             return noErr;
  99.     }
  100.     
  101.     return kUSBUnknownRequestErr;
  102. }
  103.  
  104. OSStatus UHIDGetHIDDescriptor (    UInt32                 inDescriptorType, 
  105.                                 UInt32                 inDescriptorIndex, 
  106.                                 UInt32 *             ioBufferSize, 
  107.                                 void *                 outBuffer)
  108. {
  109.     UInt32        bytesToCopy = *ioBufferSize;
  110.     void *        sourcePtr = nil;
  111.     UInt32        index;
  112.     OSStatus    status = noErr;
  113.     
  114.     // we don't need a connection, because we want anyone to be ablt to do these
  115.  
  116.     // are we looking for the HID descriptor?
  117.     if (inDescriptorType == kUSBHIDDesc || (inDescriptorType == 0 && inDescriptorIndex == 0))
  118.     {
  119.  
  120.         if (bytesToCopy > myUniversalPB.hidDiscriptor.d.descLen)
  121.             bytesToCopy = myUniversalPB.hidDiscriptor.d.descLen;
  122.         
  123.         sourcePtr = &myUniversalPB.hidDiscriptor;
  124.     }
  125.     else
  126.     {
  127.         Boolean    foundIt = false;
  128.  
  129.         for (index = 0; index < myUniversalPB.hidOwnedDescriptorsCount; index++)
  130.         {
  131.             // are we indexing for a specific type?
  132.             if (inDescriptorType != 0)
  133.             {
  134.                 if (inDescriptorType == myUniversalPB.hidOwnedDiscriptors[index].type &&
  135.                     inDescriptorIndex == myUniversalPB.hidOwnedDiscriptors[index].typeIndex)
  136.                     foundIt = true;
  137.             }
  138.             // otherwise indexing across descriptors in general
  139.             else if (inDescriptorIndex == index + 1)
  140.                 foundIt = true;
  141.                 
  142.             if (foundIt)
  143.             {
  144.                 if (bytesToCopy > myUniversalPB.hidOwnedDiscriptors[index].length)
  145.                     bytesToCopy = myUniversalPB.hidOwnedDiscriptors[index].length;
  146.                 
  147.                 sourcePtr = myUniversalPB.hidOwnedDiscriptors[index].descriptor;
  148.                 break;
  149.             }
  150.         }
  151.     }
  152.     
  153.     if (sourcePtr)
  154.     {
  155.         *ioBufferSize = bytesToCopy;
  156.         BlockMoveData(sourcePtr, outBuffer, bytesToCopy);
  157.     }
  158.     else
  159.         status = fnfErr;
  160.  
  161.     return status;
  162. }
  163.  
  164. OSStatus UHIDClaimDevice (UHIDModuleConnectionID * connectionID, UInt32 reserved)
  165. {
  166. #pragma unused (reserved)
  167.  
  168.     if (deviceIsClaimed) return openErr;
  169.     
  170.     deviceIsClaimed = true;
  171.     
  172.     *connectionID = ++currentConnectionID;
  173.     
  174.     return noErr;
  175. }
  176.  
  177. OSStatus UHIDReleaseDevice (UHIDModuleConnectionID connectionID)
  178. {
  179.     // only allow our current client to do this
  180.     if (connectionID != currentConnectionID)
  181.         return permErr;
  182.     
  183.     if (!deviceIsClaimed) return closErr;
  184.     
  185.     deviceIsClaimed = false;
  186.     return noErr;
  187. }
  188.  
  189. void NotifyRegisteredHIDUser(UInt8 hidReport[])
  190. {
  191.     // don't bother deferring it if we don't have a client interrupt installed
  192.     if (myUniversalPB.pClientInterruptRoutine)
  193.     {
  194.         // find the spot we're gonna put it
  195.         UInt32    insertIndex = myUniversalPB.deferredHIDRing_Head;
  196.         
  197.         // increment and renormalize the head
  198.         if (++myUniversalPB.deferredHIDRing_Head >= kDeferredHIDReportRingBufferSize)
  199.             myUniversalPB.deferredHIDRing_Head = 0;
  200.         
  201.         // if its full, we throw out the oldest one by incrementing the tail
  202.         if (myUniversalPB.deferredHIDRing_Head == myUniversalPB.deferredHIDRing_Tail)
  203.         {
  204.             // increment and renormalize the tail
  205.             if (++myUniversalPB.deferredHIDRing_Tail >= kDeferredHIDReportRingBufferSize)
  206.                 myUniversalPB.deferredHIDRing_Tail = 0;
  207.             
  208.             // put in the expert log that we blew out our buffer
  209.             USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: HID report ring buffer full", 0);
  210.         }
  211.         
  212.         // copy the actual data into our ring buffer
  213.         BlockMoveData (hidReport, 
  214.                        &myUniversalPB.deferredHIDReports[insertIndex * kMaxHIDReportSize], 
  215.                        myUniversalPB.maxPacketSize);
  216.         
  217.         // defer until virtual memory safe time (so our clients don't have to be marked resident)
  218.         DeferUserFn(&interruptCallback,0);
  219.     }
  220. }
  221.  
  222. void DeferredNotifyRegisteredHIDUser(void * unused)
  223. {
  224. #pragma unused(unused)
  225.  
  226.     // find the spot from which we're gonna remove it
  227.     UInt32    removeIndex = myUniversalPB.deferredHIDRing_Tail;
  228.     
  229.     // check to see if we're empty, if so, something weird happened, so log it and exit
  230.     if (myUniversalPB.deferredHIDRing_Tail == myUniversalPB.deferredHIDRing_Head)
  231.     {
  232.         // put in the expert log that we blew out our buffer
  233.         USBExpertStatus(myUniversalPB.interfaceRef, "\pUSBUniversalModule: HID report ring buffer unexpectedly empty", 0);
  234.         
  235.         // bail out
  236.         return;
  237.     }
  238.     
  239.     // call our client, if installed
  240.     if (myUniversalPB.pClientInterruptRoutine)
  241.     {
  242.         (*myUniversalPB.pClientInterruptRoutine)(
  243.                     (void *) &myUniversalPB.deferredHIDReports[removeIndex * kMaxHIDReportSize], 
  244.                     myUniversalPB.clientRefCon);
  245.     }
  246.  
  247.     // increment and renormalize the tail
  248.     if (++myUniversalPB.deferredHIDRing_Tail >= kDeferredHIDReportRingBufferSize)
  249.         myUniversalPB.deferredHIDRing_Tail = 0;
  250.     
  251. }
  252.  
  253. UHIDModuleDispatchTable TheUHIDModuleDispatchTable =
  254. {
  255.     kCurrentDispatchTableVersion,
  256.     kOldestCompatableDispatchTableVersion,
  257.     0x05ac,                    // Apple
  258.     0,
  259.     0,
  260.     (UHIDGetDeviceInfoProcPtr) UHIDGetDeviceInfo,
  261.     (UHIDClaimDeviceProcPtr) UHIDClaimDevice,
  262.     (UHIDReleaseDeviceProcPtr) UHIDReleaseDevice,
  263.     (UHIDInstallInterruptProcPtr) UHIDInstallInterrupt,
  264.     (UHIDControlDeviceProcPtr) UHIDControlDevice,
  265.     (UHIDGetHIDDescriptorProcPtr) UHIDGetHIDDescriptor
  266. };
  267.